package tech.edwardvan.springsecuritydemo.rbac.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import tech.edwardvan.springsecuritydemo.rbac.entity.SysPermission;
import tech.edwardvan.springsecuritydemo.rbac.entity.SysRolePermission;
import tech.edwardvan.springsecuritydemo.rbac.entity.SysUser;
import tech.edwardvan.springsecuritydemo.rbac.entity.SysUserRole;
import tech.edwardvan.springsecuritydemo.rbac.mapper.PermissionMapper;
import tech.edwardvan.springsecuritydemo.rbac.mapper.RolePermissionMapper;
import tech.edwardvan.springsecuritydemo.rbac.mapper.UserMapper;
import tech.edwardvan.springsecuritydemo.rbac.mapper.UserRoleMapper;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * RBAC UserDetailsService
 *
 * @author EdwardVan
 */
@Service
@RequiredArgsConstructor
public class RbacUserDetailServiceImpl implements UserDetailsService {

    private final UserMapper userMapper;

    private final UserRoleMapper userRoleMapper;

    private final RolePermissionMapper rolePermissionMapper;

    private final PermissionMapper permissionMapper;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        if (StrUtil.isEmpty(username)) {
            throw new RuntimeException("用户名不存在");
        }
        LambdaQueryWrapper<SysUser> lambdaQueryWrapper = Wrappers.lambdaQuery();
        lambdaQueryWrapper.eq(SysUser::getUsername, username);
        SysUser user = userMapper.selectOne(lambdaQueryWrapper);
        if (user == null) {
            throw new UsernameNotFoundException("用户不存在");
        }
        //根据用户名加载用户权限
        Long userId = user.getId();
        List<GrantedAuthority> userAuthority = getUserAuthority(userId);
        return new User(user.getUsername(), user.getPassword(), userAuthority);
    }

    private List<GrantedAuthority> getUserAuthority(Long userId) {
        List<GrantedAuthority> authorityList = new ArrayList<>();
        List<Long> roleIds = new ArrayList<>();
        //查询这个Id有哪些角色
        LambdaQueryWrapper<SysUserRole> userRoleQueryWrapper = Wrappers.lambdaQuery();
        userRoleQueryWrapper.eq(SysUserRole::getUserId, userId);
        userRoleQueryWrapper.select(SysUserRole::getRoleId);
        List<SysUserRole> userRoles = userRoleMapper.selectList(userRoleQueryWrapper);
        if (!userRoles.isEmpty()) {
            userRoles.forEach(userRole -> {
                Long roleId = userRole.getRoleId();
                roleIds.add(roleId);
            });
        }
        if (!roleIds.isEmpty()) {
            //获取角色Id对应的权限Id
            LambdaQueryWrapper<SysRolePermission> queryWrapper = Wrappers.lambdaQuery();
            queryWrapper.select(SysRolePermission::getPermissionId);
            queryWrapper.in(SysRolePermission::getRoleId, roleIds);
            List<SysRolePermission> rolePermissions = rolePermissionMapper.selectList(queryWrapper);
            //获取权限Id
            if (!rolePermissions.isEmpty()) {
                Set<Long> permissonIds = rolePermissions.stream().map(SysRolePermission::getPermissionId).collect(Collectors.toSet());
                //查询这些权限Id对应的permission_value和path
                LambdaQueryWrapper<SysPermission> permissionQueryWrapper = Wrappers.lambdaQuery();
                permissionQueryWrapper.select(SysPermission::getPermissionValue, SysPermission::getPath);
                permissionQueryWrapper.in(SysPermission::getId, permissonIds);
                List<SysPermission> permissions = permissionMapper.selectList(permissionQueryWrapper);
                if (!permissions.isEmpty()) {
                    //获取permission_value和path
                    return parseAuthority(authorityList, permissions);
                }
            }
        }
        return authorityList;
    }

    private List<GrantedAuthority> parseAuthority(List<GrantedAuthority> authorityList, List<SysPermission> permissions) {
        //给用户授权
        permissions.forEach(permission -> {
            authorityList.add(new SimpleGrantedAuthority(permission.getPermissionValue()));
            authorityList.add(new SimpleGrantedAuthority(permission.getPath()));
        });
        return authorityList;
    }

}
